package com.tool.cn.freemaker;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.tool.cn.util.StringUtil;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;



/**
 * 基于freemaker生成代码模板生成action、server、dao层代码
 * @author wangzh
 * 2018年7月9日 下午2:46:56
 */
public class GenerateTemplate {
	
	
	private static final String classAuthor = "zonghui_wang"; // 作者姓名
	private static String functionName = "生成测试类"; // 功能描述
	private static final Class<?> modelClass = GenerateTemplate.class;// 要依赖的实体类[GenerateEntity.java生成的实体]
	
	private static String targetClassPath = modelClass.getResource("/").toString().replace("file:/", "");
	private static String rootUrl="./template";
	
	
	public static void main(String[] args) throws Exception {

		boolean isHas = false;

		// 通过model类获取路径信息
		// 目录生成结构：{packageName}/{moduleName}/{dao,service,action}/{className}
		String path = modelClass.getPackage().getName(); // com.javaosc.user.model
		path = path.substring(0, path.lastIndexOf(".")); // com.javaosc.user
		String packageName = path.substring(0, path.lastIndexOf("."));// com.javaosc
		String moduleName = path.substring(path.lastIndexOf(".") + 1);// user
		String className = StringUtils.uncapitalize(modelClass.getSimpleName());// role

		if (StringUtil.isEmpty(packageName) || StringUtil.isEmpty(moduleName) || StringUtil.isEmpty(className) || StringUtil.isEmpty(functionName)) {
			System.out.println("参数设置错误：包名、模块名、类名、功能名不能为空。");
			return;
		}
		System.out.println("=========== 包解析如下 ===========");
		System.out.println("path: " + path);
		System.out.println("packageName: " + packageName);
		System.out.println("moduleName: " + moduleName);
		System.out.println("className:" + className);
		System.out.println("=========== 解析完毕  ===========");

		// 获取类路径
		String classPathPack = modelClass.getPackage().toString().replace("package", "").trim() + ".";
		String classPathPackPath = classPathPack.replaceAll("\\.", "/");
		String classPath = null;;
		
		int targetIndex = targetClassPath.indexOf("/target");
		if(targetIndex>0){
			classPath = targetClassPath.substring(0, targetIndex) + "/src/main/java/"  + classPathPackPath;
		}else{
			targetIndex = targetClassPath.indexOf("/bin");
			classPath= targetClassPath.substring(0, targetIndex)+"/src/"+classPathPackPath;
		}
		


		// 定义模板变量
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("packageName", StringUtils.lowerCase(packageName));
		param.put("moduleName", StringUtils.lowerCase(moduleName));
		param.put("uncapitalizeName", StringUtils.uncapitalize(className)); //首字母小写
		param.put("capitalizeName", StringUtils.capitalize(className)); //首字母大写
		param.put("author", StringUtils.isNotBlank(classAuthor) ? classAuthor : "bigaka generate");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置格式化格式
		String nowDate = sdf.format(new Date());
		param.put("date", nowDate);// 当前时间
		param.put("functionName", functionName);

		boolean flag = false;
		
		// 生成Dao 接口
		String filePath = classPath.replace("model", "dao") + param.get("capitalizeName") + "Dao.java";
		File outFile = new File(filePath);
		if(outFile.exists()){
			isHas = true;
		}else{
			flag = createFile(param, "dao.ftl", outFile);
			if (flag) {
				System.out.println("生成文件的路径：" + filePath);
			} else {
				System.out.println(param.get("capitalizeName") + "Service.java 创建失败!");
			}
		}
		

		// 生成DaoImpl 接口实现类
		filePath = classPath.replace("model", "dao") + param.get("capitalizeName") + "DaoImpl.java";
		outFile = new File(filePath);
		if(outFile.exists()){
			isHas = true;
		}else{
			flag = createFile(param, "daoImpl.ftl", outFile);
			if (flag) {
				System.out.println("生成文件的路径：" + filePath);
			} else {
				System.out.println(param.get("capitalizeName") + "DaoImpl.java 创建失败!");
			}
		}
		
		
		// 生成 Service 接口
		filePath = classPath.replace("model", "service") + param.get("capitalizeName") + "Service.java";
		String servicePath = filePath;
		
		outFile = new File(servicePath);
		if(outFile.exists()){
			isHas = true;
		}else{
			flag = createFile(param, "service.ftl", outFile);
			if (flag) {
				System.out.println("生成文件的路径：" + servicePath);
			} else {
				System.out.println(param.get("capitalizeName") + "Service.java 创建失败!");
			}
		}
		

		// 生成 ServiceImpl 接口实现类
		filePath = classPath.replace("model", "service") + param.get("capitalizeName") + "ServiceImpl.java";
		outFile = new File(filePath);
		if(outFile.exists()){
			isHas = true;
		}else{
			flag = createFile(param, "serviceImpl.ftl", outFile);
			if (flag) {
				System.out.println("生成文件的路径：" + filePath);
			} else {
				System.out.println(param.get("capitalizeName") + "ServiceImpl.java 创建失败!");
			}
		}

		// 生成 Action
		filePath = classPath.replace("model", "action") + param.get("capitalizeName") + "Action.java";
		String actionPath = filePath;
		
		outFile = new File(actionPath);
	
		if(outFile.exists()){
			isHas = true;
		}else{
			flag = createFile(param, "action.ftl", outFile);
			if (flag) {
				System.out.println("生成文件的路径：" + actionPath);
			} else {
				System.out.println(param.get("capitalizeName") + "Action.java 创建失败!");
			}
		}

		if (!isHas && flag) {
			System.out.println("提示：模块创建完毕，请验证！");
		} else {
			System.out.println("提示：为防止生成覆盖，已生成的文件不做处理，若要重新生成，请删除原来的文件(注意代码备份！)");
		}

	}
	
	
	public static boolean createFile(Map<String, Object> param, String templateFile, File outFile){
		Configuration cfg=new Configuration(Configuration.getVersion());
		
		try {
			if(!outFile.getParentFile().exists()){
				outFile.getParentFile().mkdirs();
			}
			
			cfg.setDirectoryForTemplateLoading(new File(rootUrl));
			Template template=cfg.getTemplate(templateFile);
			
			Writer javaWriter = new FileWriter(outFile);
			template.process(param, javaWriter);
			javaWriter.flush();
			javaWriter.close();
			
			
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		} catch (TemplateException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

}
